package com.template.controller;

import com.template.common.annotation.Authority;
import com.template.common.lang.BaseContext;
import com.template.common.lang.R;
import com.template.common.validgroup.Create;
import com.template.common.validgroup.Update;
import com.template.domain.entity.SysUser;
import com.template.domain.entity.UserRole;
import com.template.domain.param.UserParams;
import com.template.domain.vo.Sys;
import com.template.domain.vo.SysUserVo;
import com.template.service.UserRoleService;
import com.template.utils.MinioUtils;
import com.template.utils.SecurityUtils;
import io.minio.errors.*;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.template.service.SysUserService;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

import static com.template.domain.entity.table.UserRoleTableDef.USER_ROLE;
import static com.template.utils.CommonUtils.null2Blank;

/**
 * 控制层。
 *
 * @author dong
 * @since 2023-09-03
 */
@Validated
@RestController
@RequestMapping("/sys-user")
@RequiredArgsConstructor
public class SysUserController {

    private final SysUserService sysUserService;

    private final UserRoleService userRoleService;

    private final MinioUtils minioUtils;

    /**
     * 用户登陆后获取的用户信息
     */
    @GetMapping
    public R<SysUserVo.Login> getUserInfo() {
        Long userId = BaseContext.getCurrentId();
        SysUserVo.Login userInfo = sysUserService.getUserInfo(userId);
        return R.success(userInfo);
    }

    /**
     * 根据用户权限获取路由
     */
    @GetMapping("/route")
    public R<List<Sys.Route>> getRouteByPerms() {
        Long userId = BaseContext.getCurrentId();
        List<Sys.Route> routes = sysUserService.getRouteByPerms(userId);
        return R.success(routes);
    }

    @PutMapping("/update/basicInfo")
    public R<String> updateBasicInfo(@Validated @RequestBody UserParams.UpdateBasic info) {
        info.setPhone(null2Blank(info.getPhone()));
        info.setEmail(null2Blank(info.getEmail()));
        info.setSignature(null2Blank(info.getSignature()));
        info.setArea(null2Blank(info.getArea()));
        SysUser userinfo = new SysUser();
        BeanUtils.copyProperties(info, userinfo);
        sysUserService.updateById(userinfo);
        return R.success();
    }

    @PutMapping("/update/avatar")
    public R<String> updateAvatar(@RequestBody MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        String filename = minioUtils.upload(file);
        String fileUrl = minioUtils.preview(filename);
        return R.success(fileUrl);
    }


    /**
     * 修改密码
     */
    @PutMapping("/password")
    public R<String> updatePwd(@Valid @RequestBody UserParams.UpdatePwd param) {
        Long userId = BaseContext.getCurrentId();
        sysUserService.updatePwd(userId, param);
        return R.success();
    }


    @Authority("sys:user:get")
    @GetMapping("/list")
    public R<List<SysUserVo.WithCreateUser>> getList() {
        List<SysUserVo.WithCreateUser> list = sysUserService.listWithCreateUser();
        return R.success(list);
    }

    @Authority("sys:user:add")
    @PostMapping
    public R<String> add(@Validated(Create.class) @RequestBody SysUser sysUser) {
        String md5Password = SecurityUtils.md5Encryption(sysUser.getPassword());
        sysUser.setPassword(md5Password);
        sysUser.setNickname(sysUser.getName());
        sysUserService.save(sysUser);
        return R.success();
    }

    @Authority("sys:user:update")
    @PutMapping
    public R<String> update(@Validated(Update.class) @RequestBody SysUser sysUser) {
        // 不可直接更改密码，请访问repass接口
        sysUser.setPassword(null);
        sysUserService.updateById(sysUser);
        return R.success();
    }

    @Authority("sys:user:repass")
    @PutMapping("/repass")
    public R<String> repass(@Validated @RequestBody UserParams.Repass sysUser) {
        sysUserService.updatePwdById(sysUser);
        return R.success();
    }

    @Authority("sys:user:remove")
    @DeleteMapping
    public R<String> delete(@NotNull(message = "id不能为空") Long id) {
        sysUserService.removeById(id);
        return R.success();
    }

    @Authority("sys:user:get")
    @GetMapping("/getRolesIdById")
    public R<List<Long>> getRolesIdByUserId(@NotNull(message = "用户id为必要参数") Long id) {
        List<UserRole> list = userRoleService.queryChain().select(USER_ROLE.ROLE_ID).where(USER_ROLE.USER_ID.eq(id)).list();
        List<Long> roleIds = list.stream().map(UserRole::getRoleId).toList();
        return R.success(roleIds);
    }

    @Authority("sys:user:assign")
    @PostMapping("/assign")
    public R<String> assign(@Validated @RequestBody UserParams.Assign data) {
        sysUserService.assignRole(data.getUserId(), data.getRoleIds());
        return R.success();
    }

}
